#include "camera.h"
#include "../lcd/bsp_lcd.h"
#include <stdbool.h>
#include <stdio.h>

#define SLAVE_OV2640_ADDRESS 0x3c

#define OV2640_PIDH_ADDRESS 0x300a
#define OV2640_PIDL_ADDRESS 0x300b

/*
 * I2C方向枚举类型
 */
enum camera_pixel {
  camera_pixel_1920_1080 = 0x0, /* 1920*1080 */
  camera_pixel_1280_720 = 0x1,  /* 1280*720 */
  camera_pixel_800_480 = 0x2,   /* 1280*720 */
};

/**
 * @brief i2c2 初始化
 *
 */
void camera_i2c2_init(void) {

  // i2c
  IOMUXC_SetPinMux(IOMUXC_UART5_TX_DATA_I2C2_SCL, 1); // gpio1_io30
  IOMUXC_SetPinConfig(IOMUXC_UART5_TX_DATA_I2C2_SCL, 0x70b0);
  IOMUXC_SetPinMux(IOMUXC_UART5_RX_DATA_I2C2_SDA, 1); // gpio1_io31
  IOMUXC_SetPinConfig(IOMUXC_UART5_RX_DATA_I2C2_SDA, 0x70b0);
  gpio_pin_config_t config;
  config.direction = kGPIO_DigitalOutput;
  config.outputLogic = 1;
  config.interruptMode = kGPIO_NoIntmode;
  gpio_init(GPIO1, 30, &config);
  gpio_init(GPIO1, 31, &config);

  i2c_init(I2C2);
}

/**
 * @brief 照相机硬件复位
 *
 */
void camera_hardware_reset(void) {

  // csi_reset
  IOMUXC_SetPinMux(IOMUXC_GPIO1_IO02_GPIO1_IO02, 0);
  gpio_pin_config_t config;
  config.direction = kGPIO_DigitalOutput;
  config.outputLogic = 0;
  config.interruptMode = kGPIO_NoIntmode;
  gpio_init(GPIO1, 2, &config);
  delay_ms(100);
  gpio_pinwrite(GPIO1, 2, 1);
  delay_ms(100);
}

/**
 * @brief 向照相机内部寄存器写数据
 *
 * @param regAddress 寄存器地址
 * @param regVal 向寄存器地址写入的值
 * @return unsigned char  传输结果,1 成功，0 失败;
 */
unsigned char camera_sensor_write(unsigned short regAddress,
                                  unsigned char regVal) {
  struct i2c_transfer xfer;
  unsigned char res = 0;

  xfer.data = &regVal;
  xfer.dataSize = 1;
  xfer.subaddressSize = 2;
  xfer.subaddress = regAddress;
  xfer.direction = kI2C_Write;
  xfer.slaveAddress = SLAVE_OV2640_ADDRESS;
  res = i2c_master_transfer(I2C2, &xfer);
  if (res) {
    printf("camera_sensor_write 失败  %d \r\n", res);
    return 0;
  } else {
    return 1;
  }
}

/**
 * @brief 从照相机内部寄存器读数据
 *
 * @param regAddress 寄存器地址
 * @return unsigned char 传输结果0 失败;
 */
unsigned char camera_sensor_read(unsigned short regAddress) {
  uint8_t data = 0;
  struct i2c_transfer xfer;
  unsigned char res = 0;

  xfer.data = &data;
  xfer.dataSize = 1;
  xfer.subaddressSize = 2;
  xfer.subaddress = regAddress;
  xfer.direction = kI2C_Read;
  xfer.slaveAddress = SLAVE_OV2640_ADDRESS;
  res = i2c_master_transfer(I2C2, &xfer);
  if (res) {
    printf("camera_sensor_read 失败 %d \r\n", res);
    return 0;
  } else {
    return data;
  }
}

/**
 * @brief 读取照相机id
 *
 * @param id id[2]数组
 */
void camera_read_id(unsigned char *id) {
  id[1] = camera_sensor_read(OV2640_PIDH_ADDRESS);
  id[0] = camera_sensor_read(OV2640_PIDL_ADDRESS);
}

void camera_Serialize_init(enum camera_pixel pixel) {
  if (pixel == camera_pixel_1920_1080) {
    // 1920*1080
    camera_sensor_write(0x3800, 0x01);
    camera_sensor_write(0x3801, 0x50);
    camera_sensor_write(0x3802, 0x01);
    camera_sensor_write(0x3803, 0xb2);
    camera_sensor_write(0x3804, 0x08);
    camera_sensor_write(0x3805, 0xef);
    camera_sensor_write(0x3806, 0x05);
    camera_sensor_write(0x3807, 0xf2);
    camera_sensor_write(0x3808, 0x07);
    camera_sensor_write(0x3809, 0x80);
    camera_sensor_write(0x380a, 0x04);
    camera_sensor_write(0x380b, 0x38);
    camera_sensor_write(0x380c, 0x09);
    camera_sensor_write(0x380d, 0xc4);
    camera_sensor_write(0x380e, 0x04);
    camera_sensor_write(0x380f, 0x60);
    camera_sensor_write(0x3810, 0x00);
    camera_sensor_write(0x3811, 0x10);
    camera_sensor_write(0x3812, 0x00);
    camera_sensor_write(0x3813, 0x04);
  } else if (pixel == camera_pixel_800_480) {
    // 1280*720
    camera_sensor_write(0x3800, 0x00);
    camera_sensor_write(0x3801, 0x00);
    camera_sensor_write(0x3802, 0x00);
    camera_sensor_write(0x3803, 0xfa);
    camera_sensor_write(0x3804, 0x0a);
    camera_sensor_write(0x3805, 0x3f);
    camera_sensor_write(0x3806, 0x06);
    camera_sensor_write(0x3807, 0xa9);
    camera_sensor_write(0x3808, 0x05);
    camera_sensor_write(0x3809, 0x00);
    camera_sensor_write(0x380a, 0x02);
    camera_sensor_write(0x380b, 0xd0);
    camera_sensor_write(0x380c, 0x07);
    camera_sensor_write(0x380d, 0x64);
    camera_sensor_write(0x380e, 0x02);
    camera_sensor_write(0x380f, 0xe4);
    camera_sensor_write(0x3810, 0x00);
    camera_sensor_write(0x3811, 0x10);
    camera_sensor_write(0x3812, 0x00);
    camera_sensor_write(0x3813, 0x04);
  } else if (pixel == camera_pixel_1280_720) {
    // 800*480
    camera_sensor_write(0x3800, 0x00);
    camera_sensor_write(0x3801, 0x00);
    camera_sensor_write(0x3802, 0x00);
    camera_sensor_write(0x3803, 0xfa);
    camera_sensor_write(0x3804, 0x0a);
    camera_sensor_write(0x3805, 0x3f);
    camera_sensor_write(0x3806, 0x06);
    camera_sensor_write(0x3807, 0xa9);
    camera_sensor_write(0x3808, 0x03);
    camera_sensor_write(0x3809, 0x20);
    camera_sensor_write(0x380a, 0x01);
    camera_sensor_write(0x380b, 0xe0);
    camera_sensor_write(0x380c, 0x07);
    camera_sensor_write(0x380d, 0x64);
    camera_sensor_write(0x380e, 0x02);
    camera_sensor_write(0x380f, 0xe4);
    camera_sensor_write(0x3810, 0x00);
    camera_sensor_write(0x3811, 0x10);
    camera_sensor_write(0x3812, 0x00);
    camera_sensor_write(0x3813, 0x04);
  }
}

/**
 * @brief 控制器初始化
 *
 */
void camera_init(void) {
  camera_i2c2_init();
  camera_hardware_reset();

  camera_Serialize_init(camera_pixel_800_480);

  CSI_GPIO_INIT();
  CSI_INIT();
  CSI_Set_Image_Parameter(800, 480);
  CSI_Refresh_DMA();
  CSI_DMA_Start_Addr(LCD_FRAMEBUF_ADDR);
  CSI_Enable_DMA(true);
}
